[Xamarin] App Actionsでアプリアイコンメニューを実装してみた
Xamarin.Essentials 1.6で「App Actions」が追加されました。何かというと、アプリアイコンを長押しすると出てくるメニューを押せるアレです。
本記事では、このApp Actionsを実装してみました。
まずは基本となるアプリを作成する
プロジェクトを新規作成する
適当なプロジェクトを新規作成します。
アプリのテンプレートはポップアップを選択します。
ビルドしてアプリを起動する
ポップアップのサンプルアプリが起動しました。このサンプルアプリに対して、App Actionsを実装します。
Androidアプリ
iOSアプリ
App Actionsを実装する
Xamarin.Essentialsの更新
Xamarin.Essentialsを1.6.0
以上に更新します。
共通処理
App.xaml.cs
にアクションの一覧と選択された際の処理を追加します。
using AppActionsSample.Services; using System.Diagnostics; using Xamarin.Forms; using Xamarin.Essentials; namespace AppActionsSample { public partial class App : Application { public App() { InitializeComponent(); AppActions.OnAppAction += AppActions_OnAppAction; DependencyService.Register<MockDataStore>(); MainPage = new AppShell(); } protected override async void OnStart() { try { await AppActions.SetAsync( new AppAction("abount", "About", icon: "icon_about"), new AppAction("browse", "Browse", icon: "icon_feed"), new AppAction("add", "Add")); } catch (FeatureNotSupportedException ex) { Debug.WriteLine("App Actions not supported"); } } protected override void OnSleep() { } protected override void OnResume() { } void AppActions_OnAppAction(object sender, AppActionEventArgs e) { if (Application.Current != this && Application.Current is App app) { AppActions.OnAppAction -= app.AppActions_OnAppAction; return; } Device.BeginInvokeOnMainThread(async () => { if (e.AppAction.Id == "about") { await Shell.Current.GoToAsync("//AboutPage"); } if (e.AppAction.Id == "browse") { await Shell.Current.GoToAsync("//ItemsPage"); } if (e.AppAction.Id == "add") { await Shell.Current.GoToAsync("//ItemsPage/NewItemPage"); } }); } } }
ドキュメントのサンプルコードでは、Navigation
の下記遷移メソッドでしたが、Browseの場合に「Root→About→Browse」という画面スタックになっていたため、Shell
を用いる方法にしています。
- Application.Current.MainPage.Navigation.PopToRootAsync();
- Application.Current.MainPage.Navigation.PushAsync(page);
他に良い方法があるのかもしれません。
Androidアプリの場合
MainActivity.cs
にIntentフィルターとOnResume()
とOnNewIntent()
を追加します。
using Android.App; using Android.Content.PM; using Android.Runtime; using Android.OS; using Android.Content; namespace AppActionsSample.Droid { [IntentFilter(new[] { Xamarin.Essentials.Platform.Intent.ActionAppAction }, Categories = new[] { Android.Content.Intent.CategoryDefault })] [Activity(Label = "AppActionsSample", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { ... } protected override void OnResume() { base.OnResume(); Xamarin.Essentials.Platform.OnResume(this); } protected override void OnNewIntent(Android.Content.Intent intent) { base.OnNewIntent(intent); Xamarin.Essentials.Platform.OnNewIntent(intent); } } }
iOSアプリの場合
AppDelegate.cs
にPerformActionForShortcutItem()
メソッドを追加します。
using Foundation; using UIKit; namespace AppActionsSample.iOS { [Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { ... } public override void PerformActionForShortcutItem(UIApplication application, UIApplicationShortcutItem shortcutItem, UIOperationHandler completionHandler) { Xamarin.Essentials.Platform.PerformActionForShortcutItem(application, shortcutItem, completionHandler); } } }
実際のアプリアイコンメニューの様子
冒頭でもあったとおり、無事に実装できました。